﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Organized
{
    // A 3D heightmap terrain generated from a heightmap texture
    public class SkySphere : Drawable3dComponent
    {
        // I3DComponent values
        Vector3 position = new Vector3(0.0f,-0.43f,0.0f);
        Matrix rotation = Matrix.Identity;
        Vector3 scale = new Vector3(2800.0f);

        BoundingBox boundingBox = new BoundingBox(new Vector3(-1), new Vector3(1));

        public Vector3 Position { get { return position; } set { position = value; } }
        public Vector3 EulerRotation
        {
            get { return MathUtil.MatrixToVector3(Rotation); }
            set { this.Rotation = MathUtil.Vector3ToMatrix(value); }
        }

        public Matrix Rotation { get { return rotation; } set { rotation = value; } }
        public Vector3 Scale { get { return scale; } set { scale = value; } }
        public BoundingBox BoundingBox { get { return boundingBox; } }


        Vector4 BottomColor = new Vector4(0.0f, 0.0f, 0.0f, 1.0f);
        Vector4 TopColor = new Vector4(0.8f,0.3f,0.9f,1.0f);
        //Vector4 BottomColor = new Vector4(0.6f, 0.6f, 0.7f, 1.0f);
        //Vector4 TopColor = new Vector4(0.8f, 0.8f, 0.9f, 1.0f);

        Texture2D cloudMap;
        Model skyDome;
        Effect effect;
        public Boolean enableFog = false;

        Matrix wMatrix;
        Matrix[] modelTransforms;
        Matrix worldMatrix;
        
        //the camera, for positioning and shader calculations

        public Camera camera;

        public bool bypassFog = true;
        private float oldFogEnd;
        private float oldFogStart;
        private float oldFogDens;
        // Constructors

      
        public SkySphere(Camera cam, Lighting _light, Vector3 _position, String texture,String model, GameScreen Parent)
            : base(_light, _position, Parent)
        {
            Setup(cam, texture, model);
        }

        void Setup(Camera cam, String texture,  String model)
        {
            camera = cam;
            // load the model
            skyDome = Engine.Content.Load<Model>(model);
            // initialize the effect 
            effect = Engine.Content.Load<Effect>("Content/Effects/skyDomeEffect");
            // add the effect to the model
            skyDome.Meshes[0].MeshParts[0].Effect = effect.Clone(Engine.GraphicsDevice);
            // load the cloudmap texture
            cloudMap = Engine.Content.Load<Texture2D>(texture);
          
        }

        public override void DrawDepthMap()
        {

           
            DrawDome("DepthMap");

        }

        public void DrawDome(string technique)
        {
            if (technique == "SkyDome")
            {
                //Engine.GraphicsDevice.RenderState.FillMode = FillMode.WireFrame;
                
                //bypass fog setting
                enableFog = Engine.GraphicsDevice.RenderState.FogEnable;

                if (bypassFog)
                {
                    Engine.GraphicsDevice.RenderState.FogEnable = false;
                    
                }
                else
                {
                    oldFogStart = Engine.GraphicsDevice.RenderState.FogStart;
                    oldFogEnd = Engine.GraphicsDevice.RenderState.FogEnd;
                    oldFogDens = Engine.GraphicsDevice.RenderState.FogDensity;
                    Engine.GraphicsDevice.RenderState.FogStart = 1500f;
                    Engine.GraphicsDevice.RenderState.FogDensity = 0.4f;
                    Engine.GraphicsDevice.RenderState.FogEnd = 4000f;
                }
                  

               

                Engine.GraphicsDevice.RenderState.DepthBufferEnable = false;
                Engine.GraphicsDevice.RenderState.DepthBufferWriteEnable = false;
                Engine.GraphicsDevice.RenderState.CullMode = CullMode.None;

                //Engine.GraphicsDevice.RenderState.FogEnable = enableFog;
                //Engine.GraphicsDevice.RenderState.FogEnd = 1400;

                modelTransforms = new Matrix[skyDome.Bones.Count];
                skyDome.CopyAbsoluteBoneTransformsTo(modelTransforms);
                wMatrix = Matrix.CreateTranslation(position) * Matrix.CreateScale(scale) * Matrix.CreateTranslation(camera.Position);
            

                foreach (ModelMesh mesh in skyDome.Meshes)
                {
                    foreach (Effect currentEffect in mesh.Effects)
                    {
                        worldMatrix = modelTransforms[mesh.ParentBone.Index] * wMatrix;
                        currentEffect.CurrentTechnique = currentEffect.Techniques[technique];
                        currentEffect.Parameters["xWorld"].SetValue(worldMatrix);
                        currentEffect.Parameters["xView"].SetValue(camera.View);
                        currentEffect.Parameters["xProjection"].SetValue(camera.Projection);
                        currentEffect.Parameters["xCloudTexture"].SetValue(cloudMap);
                        currentEffect.Parameters["xTopColor"].SetValue(TopColor);
                        currentEffect.Parameters["xBottomColor"].SetValue(BottomColor);
                       
                    }
                    mesh.Draw();
                }

                Engine.GraphicsDevice.RenderState.DepthBufferWriteEnable = true;
                Engine.GraphicsDevice.RenderState.DepthBufferEnable = true;
                Engine.GraphicsDevice.RenderState.FogEnable = enableFog;

                if (!bypassFog)
                {

                    Engine.GraphicsDevice.RenderState.FogStart = oldFogStart;
                    Engine.GraphicsDevice.RenderState.FogDensity = oldFogDens;
                    Engine.GraphicsDevice.RenderState.FogEnd = oldFogEnd;
                }

               // Engine.GraphicsDevice.RenderState.DepthBufferWriteEnable = true;
                //Engine.GraphicsDevice.RenderState.DepthBufferEnable = true;
                //Engine.GraphicsDevice.RenderState.FogEnable = !enableFog;
                Engine.GraphicsDevice.RenderState.FillMode = FillMode.Solid;
            }

            if (technique == "DepthMap")
            {

                foreach (ModelMesh mesh in skyDome.Meshes)
                {
                    foreach (Effect currentEffect in mesh.Effects)
                    {
                        worldMatrix = modelTransforms[mesh.ParentBone.Index] * wMatrix;
                        currentEffect.CurrentTechnique = currentEffect.Techniques[technique];
                        effect.Parameters["xView"].SetValue(camera.View);
                        effect.Parameters["xProjection"].SetValue(camera.Projection);
                        effect.Parameters["xWorld"].SetValue(worldMatrix);                    
                        
                    }
                    mesh.Draw();
                }


            }

        }

        

        public override void Draw()      
        {
            //add me to the component render list, for postproceccing a depthmap
            //this.Parent.DrawableRenderList.Add(this);

            DrawDome("SkyDome");
        }


    }
}

